home *** CD-ROM | disk | FTP | other *** search
/ Your Choice 3 / Your Choice Software Collection 3.iso / prgmming / swag08 / misc.swg < prev    next >
Text File  |  1994-09-22  |  81KB  |  1 lines

  1. SWAGOLX.EXE (c) 1993 GDSOFT  ALL RIGHTS RESERVED 00012                                                                           1      08-24-9413:23ALL                      IAN LIN                  **APPENDING EXE**        SWAG9408    ½sñ    12     èo   {πThere's a problem here. You can append the binary data but that won't makeπcode from both EXE files work. Either the first one will work, ignoringπthe code from the second one, or the whole thing will turn into trash.ππHowever, if you still want to try it, go ahead. Here are 3 untested byπcompiling file copying programs that will only append IT2.EXE to the end ofπIT.EXE. You'll be required to make or copy files called IT.EXE and IT2.EXEπfor the use of this simple demonstration program.π}ππProgram BCopy1;πuses objects;πvarπ f,f2:tdosstream;πbeginπ f.init ('IT.EXE',stopen);π f.seek (f.getsize);π f2.init ('IT2.EXE',stopen);π f.copyfrom(f2,f2.getsize);π f.done;π f2.done;πend.ππProgram BCopy2;πvarπ f,f2:file;π blocks:longint;π bytes:word;π buffer:array [1..2048] of byte;πbeginπ assign(f,'IT.EXE');π assign(f2,'IT2.EXE');π reset(f,1);π reset(f2,1);π seek(f,filesize(f));π bytes:=filesize(f2);π blocks:=bytes div 2048;π bytes:=bytes mod 2048;π while blocks>0 do beginπ  blockread(f2,buffer,sizeof(buffer));π  blockwrite(f,buffer,sizeof(buffer));π  dec(blocks);π end;π if bytes>0 then beginπ  blockread(f2,buffer,bytes);π  blockwrite(f,buffer,bytes);π end;π close(f);π close(f2);πend.ππProgram BCopy3;πuses dos;πbeginπ swapvectors;π exec(getenv('comspec'),'/c copy /b it.exe+it2.exe it.exe');π swapvectors;πend.ππ                                                                                          2      08-24-9413:27ALL                      FRANK DIACHEYSN          Procedure Calls          SWAG9408    C╨ε    9      èo   {π  Coded By Frank Diacheysn Of Gemini Softwareππ  PROCEDURE CALLFUNCTIONππ  Input......: UserRoutine = Pointer To The Routine To Callπ             : NA          = String To Pass To <UserRoutine>π             :π             :π             :ππ  Output.....: Noneπ             :π             :π             :π             :ππ  Example....: PROCEDURE CALLME(Str:STRING);π             : BEGINπ             :   WriteLn(Str);π             : END;π             :π             : MyPointer := @CallMe;π             : CallFunction(MyPointer,'Calling You!');ππ  Description: Used To Call A Function Or A Procedure, Mainly Aπ             : Procedure, Since Output Of The Function Can't Beπ             : Returned.π             :π             :ππ}πPROCEDURE CALLFUNCTION(UserRoutine:POINTER; NA:STRING);π  PROCEDURE InsideCallFunction(NA:STRING);π  INLINE( $FF/$5E/<UserRoutine );πBEGINπ  InsideCallFunction(NA);πEND;π                                                                                                                        3      08-24-9413:28ALL                      J.P KARRELL              Config File              SWAG9408    4å∩¿    26     èo   {π >Can anyone give me an idea of how to use a config file in my programs.π >Such as an easy one, I am writing a program for my BBS in which thisπ >program will Copy files to another directory.  I know I could put theπ >directory from and to in the code itself, but what I want to accomplishπ >is to use a Configuration file to read the from directory and toπ >directory.  This is so the program can be used anywhere. Can someoneπ >please help me with this?ππI posted a unit I wrote a day or so ago which can be modified to do this.πHere it is again (extensively modified to support an ASCII configurationπfile):ππNotes: Change the CFGKEYS constants to the keywords you want your programπto recognize (remember to change the CONFIGOPTIONS constant also).ππ}ππUnit CFG_DEF;ππInterface uses Dos;  { Dos unit is needed for FindFirst }ππConstππCONFIGFILE = 'YOURFILE.CFG';πCONFIGOPTIONS = 5;πCFGKEYS : array[1..CONFIGOPTIONS] of string = ('YOUR',π                                               'CONFIG',π                                               'OPTIONS',π                                               'GO',π                                               'HERE');ππProcedure Read_Cfg_File;ππImplementation {----------------------------------------------}ππFunction Findfile(searchkey : string) : boolean;π var srec : searchrec;πbeginπ findfirst(searchkey,anyfile, srec);π FindFile := (doserror = 0);πend;ππFunction Uppercase(st : string) : string;π var loop : byte;πbeginπ for loop := 1 to length(st) do st[loop] := upcase(st[loop]);π uppercase := st;πend;ππProcedure Read_Cfg_File;π var f :text; i, j, loop : byte; line, key, command : string;π     Result_Table : array[1..CONFIGOPTIONS] of boolean;πbeginπfillchar(Result_Table,sizeof(Result_Table),false);πcommand := #0;πline := #0;πkey := #0;ππ{$I-}πassign(f,CONFIGFILE);πreset(f);π{$I+}π{CheckError(IOResult,CFGFILE);  <--- Add your own error checking here asπ                                     my CheckError procedure is not includedπ                                     in this snippet. }π while not EOF(f) do begin {while}π readln(f,line);ππ if (copy(line,1,1) <> #59) andπ    (copy(line,1,1) <> #32) then begin  { ignore lines preceeded with aπ                                         comment delimiter - usually #59π                                         (IE: ';')}π   j := pos(#32,line);ππ   if j = 0 then j := length(line)+1;π     key := copy(line,1,j-1);π     delete(line,1,j);π   i := pos(#59,line);ππ   if i = 0 then i := length(line)+1;ππ   command := copy(line,1,i-1);π   i := pos(#32,command);π   if i <> 0 then delete(command,i,length(command)-(i-1));ππ     for loop := 1 to CONFIGOPTIONS do begin {loop}π       if Uppercase(key) = CFGKEYS[loop] then begin {if}π         Result_Table[loop] := true;π         case loop of {case}π            1 : beginπ                end;π            2 : beginπ                end;π            3 : beginπ                end;π            4 : beginπ                end;π            5 : beginπ                end;π             end; {case}π          end; {if}π       end; {loop}π    end; {if}π end; {while}πclose(f);πend; {proc}ππend. {unit}π                                                       4      08-24-9413:30ALL                      WIM VAN DER VEGT         DBase III Routines       SWAG9408    C┘╛¥    283    èo   {---------------------------------------------------------}π{  Unit    : Dbase III Access Routines                    }π{  Auteur  : Ir. G.W. van der Vegt                        }π{            Hondsbroek 57                                }π{            6121 XB Born                                 }π{---------------------------------------------------------}π{  Datum .tijd  Revisie                                   }π{  910701.2130  Creatie.                                  }π{  910702.1000  Minor Errors Corrected                    }π{               Replace, Append & Pack Added              }π{  910706.2400  dbrec on the Heap (recsize max 64kB-16)   }π{               Uppercase Conversion in Bd3_fileno        }π{               Optional Halt on (fatal) Errors           }π{  910710.1500  Memo Field Support                        }π{  910715.2330  Field2num bug fixed (leading sp. removed) }π{  910960.1130  Fieldno Out of range detection            }π{  920116.1000  Two minor bugs fixed                      }π{  920124.2200  Header updated when file is closed,       }π{               Db3_Seekbof & Db3_Seekeof added           }π{               Db3_Findfirst & Db3_Findnext implemented  }π{               for wildcard search of records            }π{               Db3_soudex & Db3_field2soundex for Soundex}π{               code (sound alike) operations             }π{               Db3_firstsoudex & Db3_nextsoundex for     }π{               soundex search on a field                 }π{  920127.1300  Dbase Slack Filespace Detection &         }π{               Correction                                }π{  920129.2115  Trailing spaces remover in Db3_field2str  }π{               Seek after truncate in Db3_open           }π{  920130.2145  Slack filespace bug removed               }π{               Db3_sort implemented (based on shakersort)}π{               Bug in Db3_date2field removed             }π{  920716.2130  Empty file pack fixed in Db3_pack         }π{  920928.2200  Obscure bug in Db3_fieldname. Fieldnames  }π{               seem to be are ASCIZ in stead of fixed    }π{               length strings.                           }π{  930927.2000  Freemem bug in db3_findnext corrected.    }π{---------------------------------------------------------}π{  To Do        Full Documentation                        }π{               Write Memo Support                        }π{               Extend Db3_pack with MemoFile Packing     }π{               Sort *.DBF in place                       }π{               Insert record in *.DBF file               }π{               Date format not always yy-mm-dd           }π{---------------------------------------------------------}ππUNIT Db3_01;ππINTERFACEππUSESπ  DOS;ππ{---------------------------------------------------------}π{----Error Handling : Returns First Error Which Occured   }π{---------------------------------------------------------}ππVARπ  db3_ernr     : INTEGER;                    {----DB3 Module Error Code}π  db3_fatal    : BOOLEAN;                    {----IF Trueπ                                                    THEN Halt(db3_ernr)π                                                  on an error}ππ  db3_memotext : TEXT;                       {----Memo File}ππ{---------------------------------------------------------}ππFUNCTION  Db3_ermsg(nr : INTEGER) : STRING;ππ{---------------------------------------------------------}π{----Initialize/Exit : Must both be Called for every file }π{---------------------------------------------------------}ππPROCEDURE Db3_open(fn : STRING);             {----Opens fn.DBF file &π                                                  Inits Internals}πPROCEDURE Db3_close;                         {----Closes fn.DBF file}ππ{---------------------------------------------------------}π{----Header Function : Get .DBF header info               }π{---------------------------------------------------------}ππFUNCTION  Db3_memo : BOOLEAN;ππFUNCTION  Db3_update : STRING;ππFUNCTION  Db3_norecs : LONGINT;ππFUNCTION  Db3_nofields : INTEGER;ππFUNCTION  Db3_reclen : INTEGER;ππ{---------------------------------------------------------}π{----File I/O : Dbase III Alike (pos etc. in records)     }π{---------------------------------------------------------}ππPROCEDURE Db3_seek(pos : LONGINT);ππFUNCTION  Db3_filesize : LONGINT;ππFUNCTION  Db3_filepos : LONGINT;ππPROCEDURE Db3_readnext;ππPROCEDURE Db3_read(pos : LONGINT);ππPROCEDURE Db3_seekeof;ππPROCEDURE Db3_seekbof;ππFUNCTION  Db3_eof : BOOLEAN;ππFUNCTION  Db3_bof : BOOLEAN;ππPROCEDURE Db3_replace(no : LONGINT);         {----First Read record &π                                                  Fill all fields}πPROCEDURE Db3_append;                        {----First Fill all Fields}ππPROCEDURE Db3_delete(no : LONGINT);ππPROCEDURE Db3_undelete(no : LONGINT);ππPROCEDURE Db3_pack;                          {----Packs File IN-PLACE}ππPROCEDURE Db3_blankrec;ππ{---------------------------------------------------------}π{----Field Operations : no is .DBF field number           }π{---------------------------------------------------------}ππFUNCTION  Db3_fieldname(no : INTEGER) : STRING;ππFUNCTION  Db3_fieldlen(no : INTEGER) : INTEGER;ππFUNCTION  Db3_fielddec(no : INTEGER) : INTEGER;ππFUNCTION  Db3_fieldno(name : STRING) : INTEGER; {----Searches Fieldnumber forπ                                                     Uppercase fieldname}πFUNCTION  Db3_fieldtype(no : INTEGER) : CHAR;ππFUNCTION  Db3_deleted : BOOLEAN;ππ{---------------------------------------------------------}π{----Field Conversions : date format 'dd-mm-19yy'         }π{---------------------------------------------------------}ππFUNCTION  Db3_field2str(no :INTEGER) : STRING;ππFUNCTION  Db3_field2char(no :INTEGER) : CHAR;ππFUNCTION  Db3_field2logic(no : INTEGER) : BOOLEAN;ππFUNCTION  Db3_field2num(no : INTEGER) : REAL;ππFUNCTION  Db3_field2date(no :INTEGER) : STRING;ππPROCEDURE Db3_field2memo(no : INTEGER);ππFUNCTION  Db3_field2soundex(no : INTEGER) : STRING;ππPROCEDURE Db3_str2field(no :INTEGER;s : STRING);ππPROCEDURE Db3_char2field(no :INTEGER;s : CHAR);ππPROCEDURE Db3_logic2field(no : INTEGER;l : BOOLEAN);ππPROCEDURE Db3_num2field(no : INTEGER;n : REAL);ππPROCEDURE Db3_date2field(no :INTEGER;d : STRING);ππ{---------------------------------------------------------}π{----Database Search, spaces are used as wildcards.       }π{    Db3_blankrec can be used for creating a wildcard     }π{    record. Then if Findfirst is true the use Findnext   }π{    until Findnext becomes false. After each succesfull  }π{    call the internal readbuffer will contain the        }π{    matching record. Use casesense=true for a case       }π{    sensitive search.                                    }π{---------------------------------------------------------}ππFUNCTION Db3_findfirst(cs : BOOLEAN) : BOOLEAN;ππFUNCTION Db3_findnext(cs : BOOLEAN) : BOOLEAN;ππ{---------------------------------------------------------}π{----Soundex Code Function (sound alike)                  }π{---------------------------------------------------------}ππFUNCTION  Db3_soundex(name : STRING) : STRING;ππFUNCTION  Db3_firstsoundex(no : INTEGER; s : STRING) : BOOLEAN;ππFUNCTION  Db3_nextsoundex(no : INTEGER; s : STRING) : BOOLEAN;ππ{---------------------------------------------------------}π{----Shaker Sort Almost Sorted *.DBF Files                }π{---------------------------------------------------------}ππPROCEDURE Db3_sort(no : INTEGER);ππIMPLEMENTATIONππ{---------------------------------------------------------}π{----Error Handling                                       }π{---------------------------------------------------------}ππPROCEDURE Seternr(e : INTEGER);ππBEGINπ  IF (db3_ernr=0) THEN db3_ernr:=e;π  IF db3_fatalπ    THENπ      BEGINπ        Writeln;π        Writeln('Db3_01 [Error : ',db3_ernr:0,' = '+Db3_ermsg(db3_ernr)+']');π        Writeln;π        IF (db3_ernr<>1) THEN Db3_close;π        Halt(e);π      END;πEND; {of Seternr}ππ{---------------------------------------------------------}ππFUNCTION  Db3_ermsg(nr : INTEGER) : STRING;ππBEGINπ  CASE nr OFπ    0 : Db3_ermsg:='No Error';π    1 : Db3_ermsg:='Error Opening File';π    2 : Db3_ermsg:='Seek Past EOF';π    3 : Db3_ermsg:='Seek Before BOF';π    4 : Db3_ermsg:='Read Past EOF';π    5 : Db3_ermsg:='Invalid Numeric Field';π    6 : Db3_ermsg:='Field Name NOT Found';π    7 : Db3_ermsg:='Invalid Header';π    8 : Db3_ermsg:='Incorrect Filesize';π    9 : Db3_ermsg:='Records to Large';π   10 : Db3_ermsg:='To many Fields';π   11 : Db3_ermsg:='Invalid Date Format';π   12 : Db3_ermsg:='Cannot Format Real';π   13 : Db3_ermsg:='Record was already deleted';π   14 : Db3_ermsg:='Record was not deleted';π   15 : Db3_ermsg:='NOT a Dbase III File';π   16 : Db3_ermsg:='Field Number NOT Found';π   17 : Db3_ermsg:='No Memofields in this file';π   18 : Db3_ermsg:='All matching records already found';π   19 : Db3_ermsg:='No *.DBF file open';π   20 : Db3_ermsg:='*.DBF already file open';π   99 : Db3_ermsg:='NOT Yet Implemented';π  ELSE Db3_ermsg:='Unkown Error';π  END;ππ  db3_ernr:=0;πEND; {of Db3_ermsg}ππ{---------------------------------------------------------}π{----Types/Vars & Constants                               }π{---------------------------------------------------------}ππTYPEπ  dbheader = RECORDπ               dbvers : BYTE;π               dbupdy,π               dbupdm,π               dbupdd : BYTE;π               dbnorec: LONGINT;π               dbheadl,π               dbrecl : INTEGER;π               dbres  : ARRAY[1..20] OF BYTE;π             END;ππ  dbfield  = RECORD                          {----Definition of Field Header}π               dbname : ARRAY[1..11] OF CHAR;π               dbtype : CHAR;π               dbadr  : LONGINT;π               dblen,π               dbdec  : BYTE;π               dbres  : ARRAY[1..14] OF CHAR;π             END;ππ  fptr     = RECORD                          {----Definition of Readbuf Index}π               fppos   : WORD;π               fplen   : BYTE;π             END;ππCONSTπ  maxfield =    60;                          {----Max number of Fields}π  maxsize  = 65000;                          {----Maximum Record Size}ππTYPEπ  rectyp   = ARRAY[0..maxsize] OF CHAR;      {----Record Readbuffer Type}ππVARπ  f        : file;                           {----.DBF File}ππ  header   : dbheader;                       {----Space for Header}π  nofields : INTEGER;                        {----Number of Fields}ππ  fields   : ARRAY[1..maxfield] OF dbfield;  {----Field Definitions}π  fieldptr : ARRAY[1..maxfield] OF fptr;     {----Index into Readbuffer}π  recstart : LONGINT;                        {----Start of Record Area}ππ  dbrec    : ^rectyp;                        {----Record Buffer}π  reclen   : WORD;                           {----Record Length}ππ  memo     : FILE;                           {----Memo File}π  memopos  : LONGINT;                        {----Location of Memo Record}π  memobuf  : ARRAY[1..512] OF CHAR;          {----Memo Text File buffer}ππ  dbsearch : ^rectyp;                        {----Search Record Buffer}ππ{---------------------------------------------------------}π{----Initialize                                           }π{---------------------------------------------------------}ππPROCEDURE Db3_open(fn : STRING);ππVARπ  i   : INTEGER;π  j   : WORD;π  ch  : CHAR;ππBEGINπ  IF (dbrec<>NIL)π    THEN Seternr(20)π    ELSEπ      BEGINπ        Assign(f,fn+'.DBF');π        {$I-} Reset(f,1); {$I+}π        IF (Ioresult<>0)π          THEN Seternr(1)π          ELSEπ            BEGINπ            {----Dump Header}π              Blockread(f,header,32);ππ              Getmem(dbrec,header.dbrecl+1);ππ            {---Scan for Fieldnames & Recordlength}π              reclen  :=1;π              nofields:=0;π              Blockread(f,ch,1);π              WHILE (nofields<maxfield) AND (ch<>#13) DOπ                BEGINπ                  Inc(nofields);π                  WITH fields[nofields] DOπ                    BEGINπ                      dbname[1]:=ch;π                      Blockread(f,dbname[2],Sizeof(dbfield)-1);π                      Inc(reclen,dblen);π                      Blockread(f,ch,1);π                    END;π                END;ππ              IF (ch<>#13) THEN Seternr(10);ππ            {----Zapped file contains only a EOF}π              recstart:=Filepos(f);ππ            {----Set fieldptr}π              j:=1;π              FOR i:=1 TO nofields DOπ                WITH fieldptr[i],fields[i] DOπ                  BEGINπ                    fplen:=dblen;π                    fppos:=j;π                    Inc(j,dblen);π                  END;ππ            {----Header Integrity Checks}π              IF NOT(header.dbvers IN [$03,$83]) THEN Seternr(15);ππ              IF ((header.dbheadl DIV 32)-1<>nofields) ORπ                  (header.dbrecl<>reclen)π                THEN Seternr(7);ππ            {----File Size Check}π              IF (header.dbnorec*reclen<>(Filesize(f)-recstart-1))π                THENπ                  BEGINπ                  {----Truncate DBASE Slack Filespace}π                  { Writeln('Truncating'); }π                    Db3_Seek(header.dbnorec+1);π                    {$I-} Seek(f,Filepos(f)+1); {$I+}π                    IF (IOresult=0)π                      THEN Truncate(f)π                      ELSE Seternr(8);π                  END;ππ              IF (reclen>Sizeof(rectyp)) THEN Seternr(9);ππ              IF Db3_memoπ                THENπ                  BEGINπ                    Assign(memo,fn+'.DBT');π                    {$I-} Reset(memo,1); {$I+}π                    IF (IOresult<>0) THEN Seternr(17);π                  END;ππ              IF (db3_ernr<>0) THEN Freemem(dbrec,header.dbrecl+1);π            END;ππ        IF (db3_ernr<>0)π          THEN dbrec:=NILπ          ELSE Db3_Seekbofππ      END;πEND; {of Db3_open}ππ{---------------------------------------------------------}ππPROCEDURE Db3_close;ππVARπ  y,m,d,dow : WORD;ππBEGINπ  IF (dbrec<>NIL)π    THENπ      BEGINπ      {----Update *.DBF File Header}π        Getdate(y,m,d,dow);π        WITH header DOπ          BEGINπ            dbupdy :=y MOD 100;π            dbupdm :=m;π            dbupdd :=d;π            dbnorec:=Db3_filesize;π          END;π        Reset(f,1);π        Blockwrite(f,header,32);π        Close(f);ππ      {----Cleanup Memory}π        Freemem(dbrec,header.dbrecl+1);π        IF dbsearch<>NIL THEN Freemem(dbsearch,header.dbrecl+1);ππ        dbrec    :=NIL;π        dbsearch :=NIL;π      ENDπ    ELSE Seternr(19);πEND; {of DB3_close}ππ{---------------------------------------------------------}π{----Header Operations                                    }π{---------------------------------------------------------}ππFUNCTION  Db3_memo : BOOLEAN;ππBEGINπ  Db3_memo:=header.dbvers=$83;πEND; {of Db3_memo}ππ{---------------------------------------------------------}ππFUNCTION  Db3_update : STRING;ππVARπ  s : STRING;ππBEGINπ  s:='dd-mm-19yy';π  s[ 1]:=Chr(Ord('0')+header.dbupdd DIV 10);π  s[ 2]:=Chr(Ord('0')+header.dbupdd MOD 10);π  s[ 4]:=Chr(Ord('0')+header.dbupdm DIV 10);π  s[ 5]:=Chr(Ord('0')+header.dbupdm MOD 10);π  s[ 9]:=Chr(Ord('0')+header.dbupdy DIV 10);π  s[10]:=Chr(Ord('0')+header.dbupdy MOD 10);ππ  Db3_update:=s;πEND; {of Db3_update}ππ{---------------------------------------------------------}ππFUNCTION  Db3_norecs : LONGINT;ππBEGINπ  Db3_norecs:=header.dbnorec;πEND; {of Db3_norecs}ππ{---------------------------------------------------------}ππFUNCTION  Db3_nofields : INTEGER;ππBEGINπ  Db3_nofields:=nofields;πEND; {of Db3_nofields}ππ{---------------------------------------------------------}ππFUNCTION  Db3_reclen : INTEGER;ππBEGINπ  Db3_reclen:=reclen;πEND; {of Db3_reclen}ππ{---------------------------------------------------------}π{----File I/O                                             }π{---------------------------------------------------------}ππPROCEDURE Db3_seek(pos : LONGINT);ππBEGINπ  {$I-} Seek(f,recstart+(pos-1)*reclen); {$I+}π  IF (Ioresult<>0) OR (pos<1) OR (pos>Db3_filesize+1)π    THENπ      BEGINπ        IF (pos>0)π          THEN Seternr(2)π          ELSE Seternr(3);π      END;πEND; {of Db3_seek}ππ{---------------------------------------------------------}ππFUNCTION  Db3_filesize : LONGINT;ππBEGINπ  Db3_filesize:=(Filesize(f)-recstart) DIV reclen;πEND; {of Db3_filesize}ππ{---------------------------------------------------------}ππFUNCTION  Db3_filepos : LONGINT;ππBEGINπ  Db3_filepos:=((Filepos(f)-recstart) DIV reclen)+1;πEND; {of Db3_filepos}ππ{---------------------------------------------------------}ππPROCEDURE Db3_readnext;ππBEGINπ  IF EOF(f) OR Db3_Eofπ    THEN Seternr(4)π    ELSE Blockread(f,dbrec^,reclen);πEND; {of Db3_readnext}ππ{---------------------------------------------------------}ππPROCEDURE Db3_read(pos : LONGINT);ππBEGINπ  Db3_seek(pos);π  Db3_readnext;πEND; {of Db3_read}ππ{---------------------------------------------------------}ππPROCEDURE Db3_seekeof;ππBEGINπ  Db3_Seek(Db3_filesize+1);πEND; {of Db3_seekeof}ππ{---------------------------------------------------------}ππPROCEDURE Db3_seekbof;ππBEGINπ  Seek(f,recstart);πEND; {of Db3_seekeof}ππ{---------------------------------------------------------}ππFUNCTION  Db3_eof : BOOLEAN;ππBEGINπ  Db3_eof:=(Filepos(f)>=Filesize(f)-1);πEND; {of Db3_eof}ππ{---------------------------------------------------------}ππFUNCTION  Db3_bof : BOOLEAN;ππBEGINπ  Db3_bof:=Filepos(f)=recstart;πEND; {of Db3_bof}ππ{---------------------------------------------------------}ππPROCEDURE Db3_replace(no : LONGINT);ππBEGINπ  Db3_seek(no);π  IF (db3_ernr=0) THEN Blockwrite(f,dbrec^[0],reclen)πEND; {of Db3_append}ππ{---------------------------------------------------------}ππPROCEDURE Db3_append;ππVARπ  ch : CHAR;ππBEGINπ  Db3_seek(Db3_filesize+1);π  Blockwrite(f,dbrec^[0],reclen);π  ch:=^Z;π  Blockwrite(f,ch,1);π  Db3_seek(Db3_filesize+1);πEND; {of Db3_append}ππ{---------------------------------------------------------}ππPROCEDURE Db3_delete(no : LONGINT);ππBEGINπ  Db3_read(no);π  IF dbrec^[0]='*'π    THEN Seternr(13)π    ELSE dbrec^[0]:='*';π  Db3_replace(no)πEND; {of Db3_delete}ππ{---------------------------------------------------------}ππPROCEDURE Db3_undelete(no : LONGINT);ππBEGINπ  Db3_read(no);π  IF dbrec^[0]=' 'π    THEN Seternr(14)π    ELSE dbrec^[0]:=' ';π  Db3_replace(no)πEND; {of Db3_undelete}ππ{---------------------------------------------------------}ππPROCEDURE Db3_pack;ππVARπ  i,j : LONGINT;π  ch  : CHAR;ππBEGINπ  j:=0;π  FOR i:=1 TO Db3_filesize DOπ    BEGINπ      Db3_read(i);π      IF NOT(Db3_deleted)π        THENπ          BEGINπ            Inc(j);π            Db3_replace(j)π          ENDπ    END;ππ{----New EOF Marker}π  IF (j=0)π    THEN db3_SeekBofπ    ELSE Db3_read(j);π  ch:=^Z;π  Blockwrite(f,ch,1);π  Truncate(f);ππ  Db3_seek(1);πEND; {of Db3_pack}ππ{---------------------------------------------------------}ππPROCEDURE Db3_blankrec;ππVARπ  i : INTEGER;ππBEGINπ  FOR i:=0 TO reclen-1 DO dbrec^[i]:=#32;πEND; {of Db3_blankrec}ππ{---------------------------------------------------------}π{----Field Operations                                     }π{---------------------------------------------------------}ππFUNCTION  Db3_fieldname(no : INTEGER) : STRING;ππVARπ  s : STRING;π  i : WORD;ππBEGINπ  s:='';π  i:=1;π  IF no IN [1..nofields]π    THENπ      BEGINπ        WITH fields[no] DOπ          WHILE (i<=Sizeof(dbname)) AND (dbname[i]<>#0) DOπ            BEGINπ              s:=s+dbname[i];π              Inc(i);π            END;π      ENDπ    ELSE Seternr(16);π  Db3_fieldname:=s;πEND; {of Db3_fieldname}ππ{---------------------------------------------------------}ππFUNCTION  Db3_fieldlen(no : INTEGER) : INTEGER;ππBEGINπ  Db3_fieldlen:=0;π  IF no IN [1..nofields]π    THEN Db3_fieldlen:=fields[no].dblenπ    ELSE Seternr(16);πEND; {of Db3_fieldlen}ππ{---------------------------------------------------------}ππFUNCTION  Db3_fielddec(no : INTEGER) : INTEGER;ππBEGINπ  Db3_fielddec:=0;π  IF no IN [1..nofields]π    THEN Db3_fielddec:=fields[no].dbdecπ    ELSE Seternr(16)πEND; {of Db3_fielddec}ππ{---------------------------------------------------------}ππFUNCTION  Db3_fieldno(name : STRING) : INTEGER;ππVARπ  i,j : INTEGER;π  s   : STRING;ππBEGINπ  Db3_fieldno:=0;ππ  s:=name;π  FOR i:=1 TO Length(s) DO s[i]:=Upcase(s[i]);ππ  i:=1;π  WHILE (i<=nofields) AND (s<>Db3_fieldname(i)) DOπ    Inc(i);ππ  IF (i>nofields)π    THEN Seternr(6)π    ELSE Db3_fieldno:=i;πEND; {of Db3_fieldno}ππ{---------------------------------------------------------}ππFUNCTION  Db3_fieldtype(no : INTEGER) : CHAR;ππBEGINπ  Db3_fieldtype:=#00;π  IF no IN [1..nofields]π    THEN Db3_fieldtype:=fields[no].dbtypeπ    ELSE Seternr(16);πEND; {of Db3_fieldtype}ππ{---------------------------------------------------------}ππFUNCTION  Db3_deleted : BOOLEAN;ππBEGINπ  Db3_deleted:=dbrec^[0]<>#32;πEND; {of Db3_deleted}ππ{---------------------------------------------------------}π{----Field Conversions                                    }π{---------------------------------------------------------}ππFUNCTION  Db3_field2str(no :INTEGER) : STRING;ππVARπ  s : STRING;π  i : WORD;ππBEGINπ  s:='';π  IF (no IN [1..nofields])π    THENπ      BEGINπ        s[0]:=Chr(fieldptr[no].fplen);π        Move(dbrec^[fieldptr[no].fppos],s[1],fieldptr[no].fplen);π      ENDπ    ELSE Seternr(16);π{----Strip Trailing Spaces}π  WHILE (Length(s)>0) AND (s[Length(s)]=#32) DO Dec(s[0]);π  Db3_field2str:=s;πEND; {of Db3_field2str}ππ{---------------------------------------------------------}ππFUNCTION Db3_field2char(no :INTEGER) : CHAR;ππVARπ  s : STRING;ππBEGINπ  IF (Db3_fieldlen(no)=1)π    THEN s:=Db3_field2str(no)π    ELSE s:=#00;ππ  IF (Length(s)=0)π    THEN Db3_field2char:=#32π    ELSE Db3_field2char:=s[1];πEND; {of Db3_field2char}ππ{---------------------------------------------------------}ππFUNCTION Db3_field2logic(no : INTEGER) : BOOLEAN;ππBEGINπ  Db3_field2logic:=(Db3_field2char(no)='T');πEND; {of Db3_field2logic}ππ{---------------------------------------------------------}ππFUNCTION  Db3_field2num(no : INTEGER) : REAL;ππVARπ  r : REAL;π  s : STRING;π  e : INTEGER;ππBEGINπ  s:=Db3_field2str(no);π  WHILE (Length(s)>0) AND (s[1]=#32) DO Delete(s,1,1);π  Val(s,r,e);π  IF (e<>0)π    THEN Seternr(5);π  Db3_field2num:=r;πEND; {of Db3_field2num}ππ{---------------------------------------------------------}ππFUNCTION  Db3_field2date(no :INTEGER) : STRING;ππVARπ  s : STRING;ππBEGINπ  s:='dd-mm-yyyy';π  IF (no IN [1..nofields])π    THENπ      BEGINπ        Move(dbrec^[fieldptr[no].fppos+6],s[1],2);π        Move(dbrec^[fieldptr[no].fppos+4],s[4],2);π        Move(dbrec^[fieldptr[no].fppos+0],s[7],4);π      ENDπ    ELSE Seternr(16);ππ  Db3_field2date:=s;πEND; {of Db3_field2date}ππ{---------------------------------------------------------}ππFUNCTION Db3_field2soundex(no : INTEGER) : STRING;ππBEGINπ  Db3_field2soundex:=Db3_soundex(Db3_field2str(no));πEND; {of Db3_field2soundex}ππ{---------------------------------------------------------}ππPROCEDURE Db3_str2field(no :INTEGER;s : STRING);ππBEGINπ  IF (no IN [1..nofields])π    THENπ      BEGINπ        Fillchar(dbrec^[fieldptr[no].fppos],fieldptr[no].fplen,#32);π        WITH fields[no] DOπ          IF (Length(s)>dblen)π            THEN Move(s[1],dbrec^[fieldptr[no].fppos],dblen)π            ELSE Move(s[1],dbrec^[fieldptr[no].fppos],Length(s));π      ENDπ    ELSE Seternr(16)πEND; {of Db3_str2field}ππ{---------------------------------------------------------}ππPROCEDURE Db3_char2field(no :INTEGER;s : CHAR);ππBEGINπ  Db3_str2field(no,s);πEND; {of Db3_char2field}ππ{---------------------------------------------------------}ππPROCEDURE Db3_logic2field(no : INTEGER;l : BOOLEAN);ππBEGINπ  IF lπ    THEN Db3_char2field(no,'T')π    ELSE Db3_char2field(no,'F')πEND; {of Db3_logic2field}ππ{---------------------------------------------------------}ππPROCEDURE Db3_num2field(no : INTEGER;n: REAL);ππVARπ  s : STRING;ππBEGINπ  IF (no IN [1..nofields])π    THENπ      BEGINπ        Str(n:fields[no].dblen:fields[no].dbdec,s);π        IF (Length(s)>fields[no].dblen)π          THEN Seternr(12)π          ELSE Db3_str2field(no,s);π      ENDπ    ELSE Seternr(16)πEND; {of Db3_num2field}ππ{---------------------------------------------------------}ππPROCEDURE Db3_date2field(no :INTEGER;d : STRING);ππVARπ  s : STRING;ππBEGINπ  IF (Length(d)<>10) ORπ     (d[3]<>'-') ORπ     (d[6]<>'-')π    THEN Seternr(11)π    ELSEπ      BEGINπ      {----dd-mm-yyyy}π        s[1]:=d[ 7];π        s[2]:=d[ 8];π        s[3]:=d[ 9];π        s[4]:=d[10];π        s[5]:=d[ 4];π        s[6]:=d[ 5];π        s[7]:=d[ 1];π        s[8]:=d[ 2];π        Db3_str2field(no,s);π      END;πEND; {of Db3_date2field}ππ{---------------------------------------------------------}π{----Memo text field support                              }π{---------------------------------------------------------}ππ{$F+}ππFUNCTION memoignore(VAR f : textrec) : INTEGER;ππBEGINπ  memoignore:=0;πEND; {of memoignore}ππ{---------------------------------------------------------}ππFUNCTION memoinput(VAR f : textrec) : INTEGER;ππVARπ  chread : WORD;ππBEGINπ  WITH Textrec(f) DOπ    BEGINπ      Blockread(memo,memobuf[1],Sizeof(memobuf),chread);π      bufpos   :=0;π      bufend   :=chread;π    END;π  memoinput:=0;πEND; {of memoinput}ππ{$F-}ππ{---------------------------------------------------------}ππPROCEDURE Assignmemo(VAR f : TEXT);ππVARπ  chread : WORD;ππCONSTπ  fminput =$D7B1;ππBEGINπ  WITH Textrec(f) DOπ    BEGINπ      handle   :=$ffff;π      mode     :=fminput;π      bufsize  :=SIZEOF(memobuf);π      bufpos   :=0;π      bufptr   :=@memobuf;ππ      Blockread(memo,memobuf[1],Sizeof(memobuf),chread);π      bufpos   :=0;π      bufend   :=chread;ππ      openfunc :=@memoignore;π      inoutfunc:=@memoinput;π      flushfunc:=@memoignore;π      closefunc:=@memoignore;π      name[0]  :=#00;π    END;πEND; {of Assignmemo}ππ{---------------------------------------------------------}ππPROCEDURE Db3_field2memo(no : INTEGER);ππVARπ  e  : INTEGER;π  s  : STRING;ππBEGINπ  IF Db3_memoπ    THENπ      BEGINπ        s:=Db3_field2str(no);π        WHILE (Length(s)>0) AND (s[1]=#32) DO Delete(s,1,1);π        Val(s,memopos,e);π        IF (e<>0)π          THEN Seternr(5)π          ELSEπ            BEGINπ              Seek(memo,memopos*Sizeof(memobuf));π              Assignmemo(db3_memotext);π            END;π      ENDπ    ELSE Seternr(17);πEND; {of Db3_field2memo}ππ{---------------------------------------------------------}ππFUNCTION Db3_findfirst(cs : BOOLEAN) : BOOLEAN;ππVARπ  match,π  found : BOOLEAN;π  i     : INTEGER;ππBEGINπ  Getmem(dbsearch,Db3_reclen+1);π  Move(dbrec^,dbsearch^,Db3_reclen);ππ  Db3_Seekbof;ππ  found:=False;π  WHILE NOT(found OR Db3_eof OR (Db3_ernr<>0)) DOπ    BEGINπ      Db3_readnext;ππ      i:=0;π      match:=true;π      WHILE (i<Db3_reclen) AND match DOπ        BEGINπ          IF (dbsearch^[i]<>#32)π            THENπ              CASE cs OFπ                TRUE  : match:=(       dbsearch^[i] =       dbrec^[i]);π                FALSE : match:=(Upcase(dbsearch^[i])=Upcase(dbrec^[i]));π              END;π          INC(i);π        END;π      found:=match;π    END;ππ  Db3_findfirst:=found;ππ  IF (found=False)π    THENπ      BEGINπ        Freemem(dbsearch,Db3_reclen+1);π        dbsearch:=NIL;π      END;πEND; {of Db3_findfirst}ππ{---------------------------------------------------------}ππFUNCTION Db3_findnext(cs : BOOLEAN) : BOOLEAN;ππVARπ  match,π  found : BOOLEAN;π  i     : INTEGER;ππBEGINπ  IF (dbsearch=NIL)π    THEN Seternr(18);ππ  found:=False;π  WHILE NOT(found OR Db3_eof OR (Db3_ernr<>0)) DOπ    BEGINπ      Db3_readnext;ππ      i:=0;π      match:=true;π      WHILE (i<Db3_reclen) AND match DOπ        BEGINπ          IF (dbsearch^[i]<>#32)π            THENπ              CASE cs OFπ                TRUE  : match:=(       dbsearch^[i] =       dbrec^[i]);π                FALSE : match:=(Upcase(dbsearch^[i])=Upcase(dbrec^[i]));π              END;π          INC(i);π        END;π      found:=match;π    END;ππ  Db3_findnext:=found;ππ  If (found=False) AND (dbsearch<>NIL)π    Thenπ      BEGINπ        Freemem(dbsearch,Db3_reclen+1);π        dbsearch:=NIL;π      END;πEND; {of Db3_findnext}ππ{---------------------------------------------------------}ππFUNCTION  Db3_soundex(name : STRING) : STRING;ππVARπ  work : STRING;π  code : CHAR;π  i,j  : INTEGER;ππ  {---------------------------------------------------------}ππ  FUNCTION Encode(VAR c: CHAR): CHAR;ππ  BEGINπ    CASE Upcase(c) OFπ      'B','F','P','V':                 encode:='1';π      'C','G','J','K','Q','S','X','Z': encode:='2';π      'D','T':                         encode:='3';π      'L':                             encode:='4';π      'M','N':                         encode:='5';π      'R':                             encode:='6';π      'A','E','I','O','U','Y':         encode:='7';π      'H','W':                         encode:='8';π    ELSE                               encode:=' ';π    END;π  END; {of Encode}ππ  {---------------------------------------------------------}ππBEGINπ{----If we can't calculate, this is the answer}π  work:='';ππ{----Skip all non alpha codes in front}π  i:=1;π  WHILE (i<=Length(name)) AND (Encode(name[i])=' ') DO Inc(i);ππ{----If any alpha characters left, start calculating the SOUNDEX code}π  IF (i<=Length(name))π    THENπ      BEGINπ      {----The first alpha letter of string is the first letter of the code}π        work:=Upcase(name[i]);π        Inc(i);ππ      {----Be sure while loop precondition is correct}π        j:=1;π        code:=#00;ππ      {----Calculate the numeric part of the code,    }π      {    with a maximum of 3 digits, stop if a non  }π      {    alpha character is encountered             }π        WHILE (i<=Length(name)) AND (j<=3) AND (code<>' ') DOπ          BEGINπ            code:=Encode(name[i]);ππ          {----If new code group then add the goup number}π            IF (code IN ['1'..'6']) AND (work[j]<>code)π              THENπ                BEGINπ                  Inc(j);π                  work:=work+code;π                END;π            Inc(i);π          END;π      END;ππ{----Return the resulting SOUNDEX code}π  Db3_soundex:=work;ππEND; {of Db3_soundex}ππ{---------------------------------------------------------}ππFUNCTION Db3_firstsoundex(no : INTEGER;s : STRING) : BOOLEAN;ππVARπ  found : BOOLEAN;π  sdx   : STRING;ππBEGINπ  Db3_Seekbof;ππ  sdx:=Db3_soundex(s);ππ  found:=False;π  WHILE NOT(found OR Db3_eof OR (Db3_ernr<>0)) DOπ    BEGINπ      Db3_readnext;π      found:=(Pos(sdx,Db3_field2soundex(no))=1);π    END;ππ  Db3_firstsoundex:=found;πEND; {of Db3_firstsoundex}ππ{---------------------------------------------------------}ππFUNCTION Db3_nextsoundex(no : INTEGER; s : STRING) : BOOLEAN;ππVARπ  found : BOOLEAN;π  sdx   : STRING;ππBEGINπ  sdx:=Db3_soundex(s);ππ  found:=False;π  WHILE NOT(found OR Db3_eof OR (Db3_ernr<>0)) DOπ    BEGINπ      Db3_readnext;π      found:=(Pos(sdx,Db3_field2soundex(no))=1);π    END;ππ  Db3_nextsoundex:=found;πEND; {of Db3_nextsoundex}ππ{---------------------------------------------------------}ππPROCEDURE Db3_sort(no : INTEGER);ππVARπ  dbsort    : ^rectyp;π  swapped   : BOOLEAN;π  i,j,l,r   : LONGINT;π  s1,s2     : STRING;π  typ       : CHAR;ππ  {---------------------------------------------------------}ππ  PROCEDURE Swap(r1,r2 : LONGINT);ππ  BEGINπ  {----Side Effects}π    i:=j;π    swapped:=True;ππ  {----the Swapping itself}π    Db3_replace(r1);π    Move(dbsort^,dbrec^,Db3_reclen);π    Db3_replace(r2);π  END; {of Swapped}ππ  {---------------------------------------------------------}ππ  FUNCTION Compare(VAR c1,c2 : STRING) : BOOLEAN;ππ  VARπ    i : INTEGER;π    s : STRING;ππ  BEGINπ    CASE typ OFπ      'M',π      'N'  : BEGINπ             {----Insert spaces for correct numeric compare}π               FOR i:=1 TO Db3_fieldlen(no)-Length(c1) DO Insert(#32,c1,i);π               FOR i:=1 TO Db3_fieldlen(no)-Length(c2) DO Insert(#32,c2,i);π             END;π      'L',π      'S',π      'C'  : BEGINπ             {----Convert to Uppercase for correct alpha compare}π               FOR i:=1 TO Length(c1) Do c1[i]:=Upcase(c1[i]);π               FOR i:=1 TO Length(c2) Do c2[i]:=Upcase(c2[i]);π             END;π      'D'  : ;π    END;ππ  {----Return TRUE if c2>c1}π    Compare:=(c2>c1);π  END; {of Compare}ππ  {---------------------------------------------------------}ππBEGINπ{----Use ShakerSort on almost sorted *.DBF file}π  Getmem(dbsort,Db3_reclen+1);π  Move(dbrec^,dbsort^,Db3_reclen);ππ  l:=2;π  r:=Db3_filesize;π  i:=r-1;ππ  swapped:=TRUE;π  typ    :=Db3_fieldtype(no);ππ  WHILE (l<=r) AND swapped DOπ    BEGINπ      swapped:=False;ππ    {----Bubble Up}π      FOR j:=r DOWNTO l DOπ        BEGINπ        {----Fetch record j-1 & save it}π          Db3_read(j-1);π          s2:=Db3_field2str(no);π          Move(dbrec^,dbsort^,Db3_reclen);ππ        {----Fetch record j}π          Db3_read(j);π          s1:=Db3_field2str(no);ππ        {----Bubble}π          IF Compare(s1,s2)π            THEN Swap(j-1,j);π        END;π      l:=i+1;ππ    {----Bubble Down}π      IF swappedπ        THENπ          BEGINπ            FOR j:=l TO r DOπ              BEGINπ              {----Fetch record j-1 & save it}π                Db3_read(j-1);π                s2:=Db3_field2str(no);π                Move(dbrec^,dbsort^,Db3_reclen);ππ              {----Fetch record j}π                Db3_read(j);π                s1:=Db3_field2str(no);ππ              {----Bubble}π                IF Compare(s1,s2)π                  THEN Swap(j-1,j);π              END;π            r:=i-1;π          END;π    END;ππ  Freemem(dbsort,Db3_reclen+1);ππ  Db3_seekbof;πEND; {of Db3_sort}ππ{---------------------------------------------------------}ππBEGINπ  db3_ernr :=0;π  db3_fatal:=False;π  dbsearch :=NIL;π  dbrec    :=NIL;πEND.πππ{ DOCUMENTATION }ππDb3_01.PAS is written byππ                Ir. G.W. van der Vegtπ                Hondbroek 57π                6121 XB Born (L)ππand uploaded as public domain software because the author likes toπshare it with other Turbo Pascal Users. Please keep the source theπway it is and write extentions as separate units.ππThis unit provides read/write access to Dbase III (Plus) *.DBF files. Theπunit is uploaded as it is, the author is not responsible for any damgageπby programs using this module. The unit is, of course, tested.ππBefore using any of the Db3 routine a program shall call Db3_open toπinitialize the file internal buffers & info. When finishing the programπshould call Db3_close to close the file & cleanup the internal buffer.ππAll routines are documented so there's not much to say about them. Accessπto the DBF file is only allowed through this unit, so the file recordπisn't exported.ππRecords must be read by Db3_read or Db3_readnext, and written by Db3_appendπor Db3_replace. All record functions use LONGINTs as parameter for addressingπrecords in the file.ππWhen a record is read, one can read the field in the record by using theπrecord number as parameter of the Db3_field2 procedures. This recordπnumber lies between 1 and maxfield. If one 's to be independend of theπlocation of the record the Db3_fieldno can be used to convert a fieldπname to the field number.ππWhen writing records fill all field with Db3_2field routines and don'tπforget to use Db3_undelete to initialize the deleted marker. It's ofπcourse also possible to read a record, modify some field and replace it.ππThe Db3_pack routine packs the file in-place, so no temp file is created.ππThis unit can't create DBase III *.DBF files as it can't write the fileπheader & fieldefinitions. It's also impossble to change the structure ofπa DBase III *.DBF database with it. This is done to keep the unit simple.πCreating & modifing databases is much easier in Dbase III Language.ππThis unit uses a special naming convention to be sure there's noπconfict with procedures from other units. All exported names haveπa three letter prefix Db3_. The 01 in the Unit name is a uniqueπversion number.π                                                                        5      08-24-9413:45ALL                      STEVE ROGERS             Frequency Analyzer       SWAG9408    !(╡°    27     èo   {πJL>  #2: Another thing, I've got this cool Lotto program where I would like toπ  >  a date file where the user can enter the weeks winning lotto numbers, thenπ  >  after a collection of weeks is made (say 10), the computer will read all tπ  >  numbers in the file and compile a list of the most frequently ocurring numπ  >  and print them out to the screen. I'm having trouble reading from and writπ  >  to the file. (I'll tackle the list compiling once that is straightened outπ  >  help?ππ  Oh Boy, Lotto programs, the concept is pregnant with possibilities!π  Ever wonder why someone with a lotto program would sell it and notπ  just win all the lottos? :)ππ  Ok, you want a frequency analyzer. Here's a start that will let youπ  enter numbers and give a frequency table of all the numbers to dateπ  (hey, this is kinda fun, maybe I'll go into the lottery seminarπ  bidness. Look out, Becky Paul!):π}ππ{$i-}πusesπ  crt;ππconstπ  MAX = 49;ππtypeπ  tFreqArray= array[0..MAX] of word;ππvarπ  freqArray : tFreqArray;ππ{----------------------}πprocedure InitFreqArray;π{ Read data file into array. If not found, zero all accumulators. }ππvarπ  FreqF : file of tFreqArray;ππbeginπ  assign(FreqF,'lotto.dat');π  reset(FreqF);π  if (ioresult=0) then beginπ    read(Freqf,freqArray);π    close(freqF);π  end else fillchar(FreqArray,sizeof(FreqArray),0);πend;ππ{----------------------}πprocedure SaveFreqArray;πvarπ  FreqF : file of tFreqArray;ππbeginπ  assign(FreqF,'lotto.dat');π  rewrite(FreqF);π  write(Freqf,freqArray);π  close(freqF);πend;ππ{----------------------}πprocedure PrintFrequencyTable;ππtypeπ  tPickRec=recordπ    Number : byte;π    Freq : word;π  end;π  tPickArray=array[0..MAX] of tPickRec;ππvarπ  PickArray : tPickArray;ππ{-----------}πprocedure SortPickArray;ππ{-----------}πprocedure Swap(One,TheOther : byte);πvarπ  tmp : tPickRec;ππbeginπ  tmp:= PickArray[One];π  PickArray[One]:= PickArray[TheOther];π  PickArray[TheOther]:= tmp;πend;ππ{----------}πvarπ  i,j,min : byte;ππbeginπ  for i:= 0 to pred(MAX) do beginπ    min:= i;π    for j:= succ(i) to MAX doπ      if (PickArray[j].freq > PickArray[min].freq) then  min:= j;π    if (min>i) then Swap(i,min);π  end;πend; {SortPickArray}ππ{--------}πvarπ  i : byte;ππbeginπ  for i:= 0 to MAX do with PickArray[i] do beginπ    Number:= i;π    Freq:= FreqArray[i];π  end;ππ  SortPickArray;π  clrscr;π  writeln;π  writeln('Frequency Table:');π  for i:= 0 to 9 doπ    writeln(PickArray[i].Number   :7,': ',PickArray[i].Freq   :5,' ',π            PickArray[i+10].Number:7,': ',PickArray[i+10].Freq:5,' ',π            PickArray[i+20].Number:7,': ',PickArray[i+20].Freq:5,' ',π            PickArray[i+30].Number:7,': ',PickArray[i+30].Freq:5,' ',π            PickArray[i+40].Number:7,': ',PickArray[i+40].Freq:5,' ');ππend; {PrintFrequencyTable}ππ{----------------------}πprocedure GetLottoNumbers;πvarπ  OneNumber : byte;π  Test : integer;π  s : string;ππbeginπ  PrintFrequencyTable;π  repeatπ    writeln;π    write('Enter lotto number (<=',MAX,', Enter to quit): ');π    readln(s);π    if (s<>'') then beginπ      val(s,OneNumber,test);π      if (test=0) then beginπ        inc(FreqArray[OneNumber]);π        PrintFrequencyTable;π      end;π    end;π  until (s='');ππend; {GetLottoNumbers}πbeginπ  InitFreqArray;π  GetLottoNumbers;π  SaveFreqArray;πend.π               6      08-24-9413:48ALL                      KLAUS WIEGAND            Re  Anti-debugging...??  SWAG9408    ╘î!╝    12     èo   {π│ Now, just to bring this home, I want to make it take over theπ│ debugging interrupts.  (INT 3, is it?)  I am just wondering if thisπ│ has been done and if anyone has some TP/TASM code already created forπ│ this purpose.ππin case the debugger executes an int1 or int 3, all you will get is theπmessage "OOPS". not really secure, but for most cases QUITE good enough.ππ}ππUnit Nodebug;ππInterfaceππ{*************************************************}π{*                                               *}π{*  All actions will be handled by the           *}π{*  initialisation and the Exitprozedure         *}π{*  thus no exported declarations needed         *}π{*                                               *}π{*************************************************}ππImplementationππUses Dos,Crt;ππVarπ   Oldint1,π   Oldint3,π   Exitsave   : Pointer;ππ    Procedure Donotdebug; Interrupt;π    Beginπ       Writeln ('OOPS??  pleeze no debuggung !!!!' );π       Writeln;π       Halt (255);π    End;ππ{$F+}π    Procedure Resetnodebug;π{$F-}π    Beginπ       Setintvec ( 1, Oldint1 );π       Setintvec ( 3, Oldint3 );π       Exitproc  := Exitsave;π    End;ππBeginπ   Exitsave := Exitproc;π   Exitproc := @Resetnodebug;π   Getintvec ( 1, Oldint1 );π   Getintvec ( 3, Oldint3 );π   Setintvec ( 3, @Donotdebug );π   Setintvec ( 1, @Donotdebug );πEnd.πππ                                                                7      08-24-9413:51ALL                      ROBBIE FLYNN             'C' Printf               SWAG9408    Γ¥6e    20     èo   USES CRT,DOS;ππ(*   Here is a procedure I made that does ABOUT the same thing as the 'C'π   Printf Does. Could someone help me add a few more features? *)ππPROCEDURE Printf(Str : String);πVarπ   X : Integer;π   y : integer;π   ky: char;π   d : boolean;ππbeginπ     d:=false;π     x:=0;π     ky:=' ';π     for x:=1 to length(str) doπ         beginπ              ky:=str[x];π              if (ky='\') and (not d) thenπ                 d:=trueπ              Elseπ              If (Ky='\') and (d) thenπ                 beginπ                      write('\');π                      d:=false;π                 endπ              Elseπ              if (ky='n') and (D) or (ky='N') And (D) thenπ                 beginπ                      writeln;π                      d:=false;π                 endπ              elseπ              if (Upcase(ky)='T') and (D) thenπ                 beginπ                      write('        ');π                      d:=false;π                 endπ              elseπ              if (Upcase(ky)='B') and (D) thenπ                 beginπ                      write(#8);π                      d:=false;π                 endπ              elseπ              if (Upcase(ky)='R') and (D) thenπ                 beginπ                      write(#13);π                      d:=false;π                 endπ              elseπ              if (Upcase(ky)='F') and (D) thenπ                 beginπ                      write(#12);π                      d:=false;π                 endππ              elseπ              if (Upcase(ky)='G') and (D) thenπ                 beginπ                      write(#7);π                      d:=false;π                 endππ              elseππ              if (not d) and (ky<>'\') thenπ                 beginπ                      write(ky);π                      d:=false;π                 end;ππ         End;πEnd;ππBeginπ     ClrScr;π     Printf('This is a Printf() procedure. a \\n will make a new line.\nSee??');π     Printf(' Making a \\\\ will display a \\. Try it! Make a \\\\n to make a');π     printf('\nAlso, a \\b will back space. \\r will carriage return. \\f is f');π     printf('.\n\\t is tab.\\gIs Beep Eg\tI just tabed.\n\rI just carriage ret');π     printf('1234567890\b. There was a 0 after the 9. I backspased over it and');π     Printf('\g\gI beeped twice by: \\g\\g\n\n\n\n');πEnd.ππππ                                                                   8      08-24-9413:55ALL                      ROLAND SKINNER           Hand Scanner Code        SWAG9408    └,¥Æ    112    èo   unit RJScan;ππ{******************************}π{                              }π{            RJScan            }π{                              }π{             v1.1             }π{                              }π{                              }π{              by              }π{                              }π{        Roland Skinner        }π{                              }π{      Copyright (c) 1992      }π{                              }π{         RJS Software         }π{                              }π{    Released to the public    }π{         domain 1994.         }π{                              }π{******************************}πππ{ Implements scanning ability for the DFI HS-3000 PLUS HANDY SCANNER or }π{ other 100% compatible hand-scanners (including certain GeniScans).    }ππ{ NOTE - This unit may be overlayed.                                    }π{      - This unit requires Turbo Pascal 6 (or above).                  }ππ{$B-,D-,F+,G-,I-,L-,O+,R-,S-,V-,X-}ππ{=============================================================================}ππinterfaceππ{-----------------------------------------------------------------------------}ππ  constπ    AnyResolution = 0;ππ{-----------------------------------------------------------------------------}ππ  typeπ    ScanError = (scOK,scNoScanner,scInvalidResolution,scIncorrectResolution,π                 scInvalidImageWidth);ππ{-----------------------------------------------------------------------------}ππ  typeπ    ScanLineBufferProc = function(LineNumber : Integer) : Pointer;π                         { NOTE - This function should return  the  address }π                         {        of the scan-buffer for the "LineNumber"th }π                         {        line. First line is number 0.             }π    DisplayScannedLineProc = procedure(LineNumber : Integer);π                             { NOTE - This  procedure  should  display  (if }π                             {        necessary)  the  "LineNumber"th  line }π                             {        that was scanned in.  First  line  is }π                             {        number 0.                             }π    StopScanningProc = function : Boolean;π                       { NOTE - This function should return "False", unless }π                       {        some  event  has  occurred  which  requires }π                       {        scanning to stop.                           }ππ{-----------------------------------------------------------------------------}ππ  function  ScanImage(DesiredResolution,MaxLinesToScan,BytesPerLine : Integer;π                      ScanLineBuffer : ScanLineBufferProc;π                      DisplayScannedLine : DisplayScannedLineProc;π                      StopScanning : StopScanningProc) : ScanError;π    {- This function will scan an image  with  width  8*"BytesPerLine"  and }π    {  height "MaxLinesToScan". It is possible to specify the resolution at }π    {  which to scan the image  in  "DesiredResolution"  (100,200,300,400). }π    {  If the resolution set on the scanner is different to that specified, }π    {  then   the   "scIncorrectResolution"   error   will   be   returned. }π    {  If "DesiredResolution" is "AnyResolution", then any resolution  will }π    {  be allowed. "scInvalidResolution" will be returned if  a  resolution }π    {  other than 100,200,300,400 or "AnyResolution" is specified.          }π    {  "ScanLineBuffer",  "DisplayScannedLine"   and   "StopScanning"   are }π    {  procedures/functions whose functions are discussed above. These must }π    {  be FAR procedures/functions.                                         }π    {  If "BytesPerLine" is too  large  for  the  scanner-resolution,  then }π    {  "scInvalidImageWidth" will be returned.                              }π    {  If scanner is not installed then "scNoScanner" is returned.          }π    {  If successful, then "scOK" will be returned.                         }π    {  This function may not work with  certain hand-scanners (if  so,  use }π    {  "GenericScanImage").                                                 }π  function  GenericScanImage(MaxLinesToScan,BytesPerLine : Integer;π                             ScanLineBuffer : ScanLineBufferProc;π                             DisplayScannedLine : DisplayScannedLineProc;π                             StopScanning : StopScanningProc) : ScanError;π    {- This  function  will  scan  an  image  in  an  analogous  manner  as }π    {  "ScanImage". However, it does not do any checks for valid resolution }π    {  or image-width. This is to allow compatibility for scanners which do }π    {  not allow for scan-resolution selection.                             }π    {  "scOK", "scNoScanner" and "scInvalidImageWidth" may be  returned  by }π    {  this function. Refer to "ScanImage" for a discussion about these.    }π  function  ScannerIsInstalled : Boolean;π    {- Returns installed-status of scanner.                                 }π  function  ResolutionOfScanner : Integer;π    {- Returns the resolution  set  on  the  scanner.  If  scanner  is  not }π    {  installed, then -1 will be returned.                                 }π    {  This function may not work with certain hand-scanners.               }ππ{=============================================================================}ππimplementationππ{-----------------------------------------------------------------------------}ππ  constπ    MaxBytesPerLine : Array[1..4] of Byte = (50,102,154,205);ππ{-----------------------------------------------------------------------------}ππ  varπ    ScannerInstalled        : Boolean;π    ScannerResolution       : Word;π    ScannerResolution100    : Byte;π    DMAChannel              : Byte;π    DMAPageRegister         : Word;π    DMACurAddrRegister      : Word;π    DMACurWordCountRegister : Word;π    DMAClearSingleMaskBit   : Byte;π    DMASetSingleMaskBit     : Byte;π    DMAModeRegisterSetting  : Byte;π    DMAWriteRequest         : Byte;π    DMATerminalCountReached : Byte;ππ{-----------------------------------------------------------------------------}ππ  procedure DetermineScannerResolution; assembler;π  varπ    Data : Byte;π  asmπ    xor     ax,axπ    jmp     @Startπ  @ResSettings:π    db      21h,41h,51h,71hπ  @Start:π    mov     dx,27Bhπ    mov     cx,300π  @1:π    in      al,dxπ    and     al,10000000bπ    jnz     @1π  @2:π    in      al,dxπ    and     al,10000000bπ    jz      @2π    loop    @1π  @3:π    in      al,dxπ    and     al,10000000bπ    jnz     @3π  @4:π    in      al,dxπ    and     al,00100100bπ    shr     al,1π    shr     al,1π    or      ah,alπ    shr     al,1π    shr     al,1π    or      ah,alπ    and     ah,00000011bπ    xor     al,alπ    xchg    al,ahπ    mov     bl,4π    sub     bl,alπ    mov     al,blπ    push    axπ    mov     bx,OFFSET (@ResSettings-1)π    add     bx,axπ    mov     al,[cs:bx]π    mov     dx,27Ahπ    out     dx,alπ    mov     Data,alπ    pop     axπ    mov     ScannerResolution100,alπ    mov     cx,100π    mul     cxπ    mov     ScannerResolution,axπ  end;ππ{-----------------------------------------------------------------------------}ππ  procedure DetermineScannerDMA; assembler;π  asmπ    mov     dx,27Bhπ    in      al,dxπ    and     al,00001010bπ    cmp     al,00001000bπ    je      @UseDMA1π    cmp     al,00000010bπ    je      @UseDMA3π    jmp     @NoDMAπ  @UseDMA1:π    mov     DMAChannel,1π    mov     DMAPageRegister,        83hπ    mov     DMACurAddrRegister,     02hπ    mov     DMACurWordCountRegister,03hπ    mov     DMAClearSingleMaskBit,  00000001bπ    mov     DMASetSingleMaskBit,    00000101bπ    mov     DMAModeRegisterSetting, 01000101bπ    mov     DMAWriteRequest,        00000001bπ    mov     DMATerminalCountReached,00000010bπ    jmp     @Exitπ  @UseDMA3:π    mov     DMAChannel,3π    mov     DMAPageRegister,        82hπ    mov     DMACurAddrRegister,     06hπ    mov     DMACurWordCountRegister,07hπ    mov     DMAClearSingleMaskBit,  00000011bπ    mov     DMASetSingleMaskBit,    00000111bπ    mov     DMAModeRegisterSetting, 01000111bπ    mov     DMAWriteRequest,        00000011bπ    mov     DMATerminalCountReached,00001000bπ    jmp     @Exitπ  @NoDMA:π    mov     DMAChannel,0π  @Exit:π  end;ππ{-----------------------------------------------------------------------------}ππ  procedure TurnScannerOn; assembler;π  asmπ    mov     dx,27Ahπ    mov     al,01hπ    out     dx,alπ  end;ππ{-----------------------------------------------------------------------------}ππ  procedure TurnScannerOff; assembler;π  asmπ    mov     dx,27Ahπ    mov     al,00hπ    out     dx,alπ  end;ππ{-----------------------------------------------------------------------------}ππ  procedure DMADelay; assembler;π  asmπ    nopπ    nopπ    nopπ  end;ππ{-----------------------------------------------------------------------------}ππ  function  DoScan(MaxLinesToScan,BytesPerLine : Integer;π                   ScanLineBuffer : ScanLineBufferProc;π                   DisplayScannedLine : DisplayScannedLineProc;π                   StopScanning : StopScanningProc) : ScanError;π  varπ    LinesScanned : Integer;π    ScanBuffer   : Pointer;π    WidthToScan  : Word absolute BytesPerLine;π    QuitScanning : Boolean;π  beginπ    if (BytesPerLine>0) and (BytesPerLine<=MaxBytesPerLine[ScannerResolution100]) thenπ    beginπ      LinesScanned := 0;π      QuitScanning := False;π      repeatπ        ScanBuffer := ScanLineBuffer(LinesScanned);π        asmπ        {-Disable DMA transfer }π          mov     al,DMASetSingleMaskBitπ          out     0Ah,alπ          call    DMADelay;π          mov     al,DMAModeRegisterSettingπ          out     0Bh,alπ          call    DMADelayπ        {-Setup Buffer address }π          les     di,ScanBufferπ          mov     dx,esπ          mov     al,dhπ          mov     cl,4π          shl     dx,clπ          shr     al,clπ          add     dx,diπ          adc     al,0π          mov     cx,dxπ          mov     dx,DMAPageRegisterπ          out     dx,alπ          call    DMADelayπ          out     0Ch,alπ          call    DMADelayπ          mov     dx,DMACurAddrRegisterπ          mov     al,clπ          out     dx,alπ          call    DMADelayπ          mov     al,chπ          out     dx,alπ          call    DMADelayπ        {-Setup bytes to transfer }π          out     0Ch,alπ          call    DMADelayπ          mov     ax,WidthToScanπ          dec     axπ          mov     dx,DMACurWordCountRegisterπ          out     dx,alπ          call    DMADelayπ          mov     al,ahπ          out     dx,alπ        {-Start DMA transfer }π          mov     dx,27Bhπ          out     dx,alπ          dec     dxπ          in      al,dx                 { DX = 027Ah }π          mov     al,DMAWriteRequestπ          out     09h,alπ          call    DMADelayπ          mov     al,DMAClearSingleMaskBitπ          out     0Ah,alπ        end;π      {-Scan line }π        asmπ          mov     bl,DMATerminalCountReachedπ        @1:π          in      al,08hπ          and     al,blπ          cmp     al,blπ          je      @2π          push    bxπ          call    StopScanningπ          pop     bxπ          or      al,alπ          jz      @1π          mov     QuitScanning,Trueπ        @2:π        end;π        DisplayScannedLine(LinesScanned);π        Inc(LinesScanned);π      until (LinesScanned=MaxLinesToScan) or QuitScanning;π      DoScan := scOK;π    endπ    elseπ      DoScan := scInvalidImageWidth;π  end;ππ{-----------------------------------------------------------------------------}ππ  function  ScanImage(DesiredResolution,MaxLinesToScan,BytesPerLine : Integer;π                      ScanLineBuffer : ScanLineBufferProc;π                      DisplayScannedLine : DisplayScannedLineProc;π                      StopScanning : StopScanningProc) : ScanError;π  beginπ    if ScannerInstalled thenπ    beginπ      if (DesiredResolution=AnyResolution) or ((DesiredResolution div 100) in [1..4]) thenπ      beginπ        TurnScannerOn;π        DetermineScannerResolution;π        if (DesiredResolution=AnyResolution) or (DesiredResolution=ScannerResolution) thenπ          ScanImage := DoScan(MaxLinesToScan,BytesPerLine,π                              ScanLineBuffer,DisplayScannedLine,StopScanning)π        elseπ          ScanImage := scIncorrectResolution;π        TurnScannerOff;π      endπ      elseπ        ScanImage := scInvalidResolution;π    endπ    elseπ      ScanImage := scNoScanner;π  end;ππ{-----------------------------------------------------------------------------}ππ  function  GenericScanImage(MaxLinesToScan,BytesPerLine : Integer;π                             ScanLineBuffer : ScanLineBufferProc;π                             DisplayScannedLine : DisplayScannedLineProc;π                             StopScanning : StopScanningProc) : ScanError;π  beginπ    if ScannerInstalled thenπ    beginπ      TurnScannerOn;π      ScannerResolution100 := 4;π      GenericScanImage := DoScan(MaxLinesToScan,BytesPerLine,π                          ScanLineBuffer,DisplayScannedLine,StopScanning);π      TurnScannerOff;π    endπ    elseπ      GenericScanImage := scNoScanner;π  end;ππ{-----------------------------------------------------------------------------}ππ  procedure DetermineScannerPresence;π  beginπ    TurnScannerOn;π    DetermineScannerDMA;π    TurnScannerOff;π    ScannerInstalled := (DMAChannel<>0);π  end;ππ{-----------------------------------------------------------------------------}ππ  function  ScannerIsInstalled : Boolean;π  beginπ    ScannerIsInstalled := ScannerInstalled;π  end;ππ{-----------------------------------------------------------------------------}ππ  function  ResolutionOfScanner : Integer;π  beginπ    if ScannerInstalled thenπ    beginπ      TurnScannerOn;π      DetermineScannerResolution;π      TurnScannerOff;π      ResolutionOfScanner := ScannerResolution;π    endπ    elseπ      ResolutionOfScanner := -1;π  end;ππ{-----------------------------------------------------------------------------}ππbeginπ  DetermineScannerPresence;πend.ππ{=============================================================================}π                                                                                  9      08-24-9417:51ALL                      WIM VAN DER VEGT         Smooth Thermobar display SWAG9408    rDq    39     èo   {πHere a sample program which shows a smoothly (graphics mode like)πanimation of a thermobar display. It works (I think) only on VGA cardsππThe trick is done by animating one character by changing it'sπbitpattern. }πππ{---------------------------------------------------------}π{  Project : Textmode thermometer bar                     }π{  Unit    : Main Program                                 }π{  By      : Wim van der Vegt                             }π{---------------------------------------------------------}π{  This program shows a thermometer bar display similar   }π{  to the ones in many installation programs. This one    }π{  however is in textmode, but smoothly animated as if in }π{  graphics mode. It is only tested on one (S)VGA card.   }π{---------------------------------------------------------}π{  Date  .Time  Revision                                  }π{  940620.1450  Creation.                                 }π{---------------------------------------------------------}ππUsesπ  Dos,π  Crt;ππConstπ  c : Array[1..16] Of Byte = (255,255,255,255,π                              255,255,255,255,π                              255,255,255,255,π                              255,255,255,255);ππ{---------------------------------------------------------}π{---Procedure to turn cursor on/off.                      }π{---------------------------------------------------------}ππProcedure Cursor(on : Boolean);ππVARπ  r : registers;ππBEGINπ  r.ah:=$03;π  r.bh:=$00;π  Intr($10,r);ππ  IF ((r.cx< $2020) AND NOT(on)) ORπ     ((r.cx>=$2020) AND on)π    THENπ      BEGINπ        r.ah:=$01;π        r.cx:=r.cx XOR $2020;π        Intr($10,r);π      END;πEND; {of Cursor}ππ{---------------------------------------------------------}π{---Procedure to wait for the vertical retrace of the VGA }π{   display. This minimizes screen flickering when the    }π{   CRTC gets reprogrammed.                               }π{---------------------------------------------------------}ππPROCEDURE Wait4Retrace;ππbeginπ  while ((Port[$3DA] AND 8) > 0) do;π  while ((Port[$3DA] AND 8) = 0) do;πend; {of Wait4Retrace;}ππ{---------------------------------------------------------}π{---Procedure to generate an animation scene for character}π{   #1. The cursor is turned off every time the procedure }π{   is called because the cursor keeps showing up when the}π{   CRTC is reprogrammed. And a cursor behind a smoothly  }π{   animated thermobar just doesn't feel right.           }π{---------------------------------------------------------}ππProcedure Reprogram(i,bperc : Byte);ππVARπ  j : integer;π  r : registers;π  w : Word;ππBeginπ{----calculate bittpattern. It goes likeπ     0π     128π     128+64π     128+64+32π     128+64+32+16π     128+64+32+16+8π     128+64+32+16+8+4π     128+64+32+16+8+4+2π     128+64+32+16+8+4+2+1 (This is equivalent to character 219 '█')π     }ππ   w:=0;π   FOR j:=1 TO i DO w:=w+BYTE(256 SHR j);π   For j:=1 To bperc Do c[j]:=w;ππ {----reprogram character #1,π      but wait for retrace so there's no flickering}π   r.ah:=$11;π   r.al:=$10;π   r.bh:=bperc;π   r.bl:=$00;π   r.cx:=$01;π   r.dx:=$01;π   r.bp:=Ofs(c);π   r.es:=Seg(c);π   Wait4Retrace;π   Intr($10,r);π  Cursor(false);πEnd; {of Reprogram}ππ{---------------------------------------------------------}π{---Main program, btw the character #1 isn't restored     }π{   because it's seldomly used by application.            }π{   a TEXTMODE(LASTMODE) statement will clear the screen  }π{   and restore character #1. So put that at the end of   }π{   program                                               }π{---------------------------------------------------------}ππVarπ  r     : registers;π  i,k   : Byte;π  bperc : Byte;ππBeginπ  Clrscr;ππ  GotoXY(20,5);π  Write('0%                50%               100%');π  GotoXY(20,4);ππ{----get bytes per character of current font,π     by requesting font data on font #0 (INT 1F)}π  r.ah:=$11;π  r.al:=$30;π  r.bh:=$00;π  Intr($10,r);π  bperc:=r.cx;ππ  textcolor(yellow);ππ{----Do a 30 character bar}π  For k:=1 To 40 Doπ    Beginπ    {----Use chr(1) to animate, however wipe it before writing it}π      Reprogram(0,bperc);π      Write(#01);ππ    {----Animate character #1}π      For i:=0 To 7 Doπ        Beginπ        {----calc bit new patterns,π             bit patterns are reversed in character generator,π             bit 7 is on the left side of a character}π          Reprogram(i,bperc);π          Delay(25);π        End;ππ   {----Replace fully animated characters by a full block fromπ        the line drawing set because animation of character #1π        will be started all over}π     GotoXY(WhereX-1,WhereY);π     Write('█');π    End;π  GotoXY(1,6);π  Cursor(true);ππ {textmode(lastmode);}πEnd. {of Main program}π                                                                                                                10     08-25-9409:05ALL                      DAVE BELL                Using C And Pascal - LinkSWAG9408    Nv¬    40     èo   (*πYK>1) I'm going to write a program in pascal that calls a function.πYK>2) That function is going to be written in C.πYK>3) Link them together to make one EXE file.ππYK>Is there anyway to do this or am I just dreaming? <g>  Thanks forπYK>any insight in this.ππYes, it is possible.  You will need to compile object code modules withπyour Pascal and C compilers, and then link them with a linker program.πUnusually, for a programming tool, the program you use for linking usuallyπhas the obvious name of LINK.EXE (as compared to such things as "grep",π"awk", "yacc" or "bison").ππThe second edition of Turbo C++ includes a set of example files for justπthis situation.ππFirst, a fragment of the C code called by the Pascal program.πππtypedef unsigned int word;πtypedef unsigned char byte;πtypedef unsigned long longword;ππextern void setcolor(byte newcolor);  /* procedure defined inπ                                         Turbo Pascal program */πextern word factor;    /* variable declared in Turbo Pascal program */ππword sqr(int i)π{π  setcolor(1);π  return(i * i);π} /* sqr */ππword multbyfactor(word w)π{π  setcolor(9);        /* note that this function accesses the Turbo Pascal */π  return(w * factor); /* declared variable factor */π} /* multbyfactor */ππ----8<---------ππThe command line compiler uses the following .CFG fileππ---8<---------ππ-wrvlπ-pπ-k-π-r-π-u-π-zCCODEπ-zPπ-zAπ-zRCONSTπ-zSπ-zTπ-zDDATAπ-zGπ-zBππ---8<------------ππFinally, the Pascal codeππ*)πprogram CPASDEMO;π(*π  This program demonstrates how to interface Turbo Pascal and Turbo C++.π  Turbo C++ is used to generate an .OBJ file (CPASDEMO.OBJ). Thenπ  this .OBJ is linked into this Turbo Pascal program using the {$L}π  compiler directive.ππ  NOTES:π    1. Data declared in the Turbo C++ module cannot be accessed fromπ       the Turbo Pascal program. Shared data must be declared inπ       Pascal.ππ    2. If the C functions are only used in the implementation sectionπ       of a unit, declare them NEAR.  If they are declared in theπ       interface section of a unit, declare them FAR.  Always compileπ       the Turbo C++ modules using the small memory model.ππ    3. Turbo C++ runtime library routines cannot be used because theirπ       modules do not have the correct segment names.  However, if youπ       have the Turbo C++ runtime library source (available fromπ       Borland), you can use individual library modules by recompilingπ       them using Pascal conventions.  If you do recompile them, makeπ       sure that you include prototypes in your C module for all Cπ       library functions that you use.ππ    4. Some of the code that Turbo C++ generates are calls to internalπ       routines. These cannot be used without recompiling the relevantπ       parts of the Turbo C++ runtime library source code.ππ  In order to run this demonstration program you will need the followingπ  files:ππ    TCC.EXE and CTOPAS.CFG orπ    TC.EXE and CTOPAS.TCππ  To run the demonstration program CPASDEMO.EXE do the following:ππ  1. First create a CPASDEMO.OBJ file compatible with Turbo Pascal 4.0π     or later using Turbo C++.ππ    a) If you are using the Turbo C++ integrated environment (TC.EXE)π       then at the DOS prompt execute:ππ       TC CTOPAS.PRJππ       then create the .OBJ file by pressing ALT-F9.ππ    b) If you are using the Turbo C++ command line version (TCC.EXE)π       then at the DOS prompt execute:ππ       TCC +CTOPAS.CFG CPASDEMO.Cππ       Note: Use the same configuration file (CTOPAS.CFG or CTOPAS.PRJ)π             when you create your own Turbo C++ modules for use withπ             Turbo Pascalππ  2. Compile and execute the Turbo Pascal program CPASDEMO.PASππ  This simple program calls each of the functions defined in the Turbo C++π  module. Each of the Turbo C++ functions changes the current display colorπ  by calling the Turbo Pascal procedure SetColor. }π*)ππuses Crt;ππvarπ  Factor : Word;ππ{$F+}  { Force Far Calls for calling to and from Turbo C }ππ{$L CPASDEMO.OBJ}  { link in the Turbo C++-generated .OBJ module }ππfunction Sqr(I : Integer) : Word; external;π{ Change the text color and return the square of I }ππfunction MultByFactor(W : Word) : Word; external;π{ Change the text color and return W * Factor - note Turbo C++'s access of }π{ Turbo Pascal's global variable.                                        }ππprocedure SetColor(NewColor : Byte); { A procedure that changes the current }πbegin                                { display color by changing the CRT    }π  TextAttr := NewColor;              { variable TextAttr                    }πend; { SetColor }ππbeginπ  Writeln(Sqr(10));                  { Call each of the functions defined   }π                                     { passing it the appropriate info.}ππ  Factor :=100;π  Writeln(MultbyFactor(10));π  SetColor(LightGray);ππend.π{π------8<----------ππTo save space, I've edited a lot of the functions out of both sourceπfiles.  I hope this works.  I don't have a DOS Pascal compiler :(π}π  11     08-25-9409:07ALL                      GREG VIGNEAULT           DOS + WorkGroups 3.11... SWAG9408    [Bô    3      èo   {π TIP for DOS compiler users:  If you've got Windows for WorkGroupsπ v3.11 with the 32-bit disk/file access enabled, compile your codeπ under a Windows "DOS box" instead of vanilla MS-DOS... you may cutπ the compiler file i/o time in half.π}              12     08-25-9409:13ALL                      MBOUSEK@INTEL9.INTEL.COM MS Excel XLOPER StructureSWAG9408    ╫àm(    52     èo   (*π   For reference...  Here are the microsoft C and my borland Pascal versionsπof the Excel "xloper" structures.  Thanks for the help!πNotes:  1) For each variant of the union in the C version of the xloperπtype there is a single comment starting "xlType...", "xlFlow...", ...πthese are actually integers from #define statements in the .H file.  I'veπused these as selectors in my "record case ..." statements (and declaredπthem as "const" in my pascal source) and eliminated them from the comments.π2) A nice compare and contrast:  Had microsoft put the xltype word (which isπat the end of the structure "xloper") first, I could have used it in my caseπselector as in "record case xltype:word of...",  the two bytes that xltypeπoccupies would become somewhat of a runtime type selector (a definite pascalπadvantage) but on the other hand, by putting it at the end, the same addressπof this data item can directly typecast to one of the union's member typesπonce xltype has been examined (you do it by hand...) a C advantage (unlessπyou are using Borland Pascal :).  3) Since Pascal does not allow "unionsπwithin unions" or "variants of variants" I've declared each sub-unionπ(variant) as a separate type, which is legal pascal.  Same effect.  4) I'veπtaken liberties in renaming some fields to make them more readable for me :}π5) The C version is 88 lines long, the Pascal one is 85.  /*could it be theπthree lines I deleted from the comments???*/ππ*******************c version*****************************************ππ/*π** XLREF structureπ**π** Describes a single rectangular referenceπ*/ππtypedef struct xlrefπ{π    WORD rwFirst;π    WORD rwLast;π    BYTE colFirst;π    BYTE colLast;π} XLREF, FAR *LPXLREF;πππ/*π** XLMREF structureπ**π** Describes multiple rectangular references.π** This is a variable size structure, defaultπ** size is 1 reference.π*/ππtypedef struct xlmrefπ{π    WORD count;π    XLREF reftbl[1];                        /* actually reftbl[count] */π} XLMREF, FAR *LPXLMREF;πππ/*π** XLOPER structureπ**π** Excel's fundamental data type: can hold dataπ** of any type. Use "R" as the argument type in theπ** REGISTER function.π**/ππtypedef struct xloperπ{π    unionπ    {π        double num;                     /* xltypeNum */π        LPSTR str;                      /* xltypeStr */π        WORD bool;                      /* xltypeBool */π        WORD err;                       /* xltypeErr */π        short int w;                    /* xltypeInt */π        structπ        {π            WORD count;                 /* always = 1 */π            XLREF ref;π        } sref;                         /* xltypeSRef */π        structπ        {π            XLMREF far *lpmref;π            DWORD idSheet;π        } mref;                         /* xltypeRef */π        structπ        {π            struct xloper far *lparray;π            WORD rows;π            WORD columns;π        } array;                        /* xltypeMulti */π        structπ        {π            unionπ            {π                short int level;        /* xlflowRestart */π                short int tbctrl;       /* xlflowPause */π                DWORD idSheet;          /* xlflowGoto */π            } valflow;π            WORD rw;                    /* xlflowGoto */π            BYTE col;                   /* xlflowGoto */π            BYTE xlflow;π        } flow;                         /* xltypeFlow */π        structπ        {π            unionπ            {π                BYTE far *lpbData;      /* data passed to XL */π                HANDLE hdata;           /* data returned from XL */π            } h;π            long cbData;π        } bigdata;                      /* xltypeBigData */π    } val;π    WORD xltype;π} XLOPER, FAR *LPXLOPER;πππ*******************pascal version************************************π*)ππ{*π** XLREF structureπ** Describes a single rectangular referenceπ*}πtypeπ    xlref_ptr  = ^xlref_type;π    xlref_type = recordπ        FirstRow    : word;π        LastRow     : word;π        FirstCol    : byte;π        LastCol     : byte;π    end;ππ{*π** XLMREF structureπ** Describes multiple rectangular references.π** This is a variable size structure, defaultπ** size is 1 reference.π*}πtypeπ    xlmref_ptr   = ^xlmref_type;π    xlmref_type  = recordπ        count   : word; {count will never be more than 30 according to doc}π        xlrefs  : array[1..32] of xlref_type;π    end;ππ{*π** XLOPER structureπ** Excel's fundamental data type: can hold dataπ** of any type. Use "R" as the argument type in theπ** REGISTER function.π**}πtypeπ    flowarg_type = record case integer ofπ        xlFlowRestart   : ( level   : integer; );π        xlFlowPause     : ( tbctrl  : integer; );π        xlFlowGoto      : ( SheetId : longint; );π    end;ππtypeπ    handle_type = record case integer ofπ        1 : ( buff : pointer );  {*data passed to XL*}π        2 : ( hand : record      {*data returned from XL*}π                offset   : word;π                selector : word;π              end; );π    end;ππtypeπ    xloper_ptr  = ^xloper_type;π    xloper_type = recordπ        val : record case word ofπ            xlTypeNum     : ( num  : double;  );π            xlTypestr     : ( str  : ^string; );π            xlTypeBool    : ( bool : word;    );π            xlTypeErr     : ( err  : word;    );π            xlTypeInt     : ( int  : integer; );π            xlTypeSref    : ( sref : recordπ                                count   : word; {*always=1*}π                                xlref   : xlref_type;π                              end; );π            xlTypeRef     : ( mref : recordπ                                xlmref  : xlmref_ptr;π                                SheetId : longint;π                              end; );π            xlTypeMulti   : ( xlarray : recordπ                                xloper  : xloper_ptr;π                                rows    : word;π                                cols    : word;π                              end; );π            xlTypeFlow    : ( flow : recordπ                                flowarg : flowarg_type;π                                row     : word;π                                col     : byte;π                                xlflow  : byte;π                              end; );π            xlTypeBigdata : ( bigdata : recordπ                                handle  : handle_type;π                                len     : longint;π                              end; );π        end;π        xltype : word;π    end;πππππ